package com.wobito.controller.operate;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.wobito.common.constants.BaseResponse;
import com.wobito.common.constants.BusinessException;
import com.wobito.common.constants.ErrorCode;
import com.wobito.common.constants.SysConstants;
import com.wobito.common.utils.DateUtils;
import com.wobito.common.utils.ResultUtils;
import com.wobito.common.utils.StringUtils;
import com.wobito.pojo.bean.*;
import com.wobito.pojo.enums.BorrowStatusEnum;
import com.wobito.pojo.vo.book.RefreshBook;
import com.wobito.pojo.vo.cabinetLat.CloseCabinetLatVO;
import com.wobito.pojo.vo.cabinetLat.OpenCabinetLatVO;
import com.wobito.pojo.vo.person.personRenewalVO;
import com.wobito.service.*;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.validation.Valid;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @Author Wangbaba
 * @Date 2024/7/1 10:09
 * @Version 1.0
 */
@RestController()
@RequestMapping("/operate/operation")
@Api(tags = "用户界面操作控制类")
public class OperateController {

    @Autowired
    private CabinetLatService cabinetLatService;
    @Autowired
    private BookService bookService;
    @Autowired
    private IBorrowService borrowService;
    @Autowired
    private IConfigTypeService configTypeService;
    @Autowired
    private IDeviceLogService deviceLogService;
    @Autowired
    private IBorrowReturnLogService borrowReturnLogService;

    @PostMapping("/openBorrowLat")
    @ApiOperation(value = "根据柜格ID开柜门操作", notes = "开柜如果是借会返回柜格中所有书的RFID，还的话只会有提示信息")
    @Transactional(rollbackFor = Exception.class)
    public BaseResponse openBorrowLat(@Valid @RequestBody OpenCabinetLatVO openCabinetLatVO) {
        CabinetLat cabinetLat = cabinetLatService.getById(openCabinetLatVO.getLatId());
        if (ObjectUtil.isEmpty(cabinetLat)) {
            throw new BusinessException(ErrorCode.SYSTEM_ERROR, "未查询到该柜格");
        }
        if (cabinetLat.getState().equals(SysConstants.STATE_SYSTEM_TY)) {
            throw new BusinessException(ErrorCode.SYSTEM_ERROR, "该柜格已停用");
        }
        CabinetLat lat = new CabinetLat();
        lat.setId(openCabinetLatVO.getLatId());
        lat.setType(SysConstants.STATE_TYPE_OPEN);
        lat.setUpdateTime(DateUtils.getNowDate());
        cabinetLatService.updateById(lat);
        deviceLogService.insertDeviceLog(new DeviceLog(openCabinetLatVO.getLatId(), DateUtils.getNowDate(), openCabinetLatVO.getPersonId(), "根据柜格ID开柜门操作"));
        if (openCabinetLatVO.getOpenType().equals(SysConstants.BOOK_TYPE_JY)) {
            //借 返回柜格中所有RFID
            List<Book> books = bookService.list(new LambdaQueryWrapper<Book>().eq(Book::getLatId, openCabinetLatVO.getLatId()).eq(Book::getState, SysConstants.STATE_FILE_ZK).eq(Book::getIsDeleted, SysConstants.STATE_SYSTEM_ZC));
            return ResultUtils.success(books.stream().map(Book::getRfid).collect(Collectors.toList()));
        } else {
            return ResultUtils.success("柜格已开");
        }
    }

    @PostMapping("/closeCabinetLat")
    @ApiOperation(value = "关闭柜门操作", notes = "还的书就放归还RFID，借的书就放借阅RFID,后端自动处理")
    @Transactional(rollbackFor = Exception.class)
    public BaseResponse closeCabinetLat(@Valid @RequestBody CloseCabinetLatVO closeCabinetLatVO) {
        //出库书籍 记录借阅日志
        if (CollectionUtil.isNotEmpty(closeCabinetLatVO.getBorrowRfids())) {
            bookService.outBoundBooks(closeCabinetLatVO.getBorrowRfids(), closeCabinetLatVO.getLatId(), closeCabinetLatVO.getPersonId());
        }
        //入库书籍 记录归还日志
        if (CollectionUtil.isNotEmpty(closeCabinetLatVO.getReturnRfids())) {
            bookService.inBoundBooks(closeCabinetLatVO.getReturnRfids(), closeCabinetLatVO.getLatId(), closeCabinetLatVO.getPersonId());
        }
        //修改柜格状态
        CabinetLat cabinetLat = new CabinetLat();
        cabinetLat.setId(closeCabinetLatVO.getLatId());
        cabinetLat.setType(SysConstants.STATE_TYPE_CLOSE);
        cabinetLat.setUpdateTime(DateUtils.getNowDate());
        cabinetLatService.updateById(cabinetLat);
        deviceLogService.insertDeviceLog(new DeviceLog(closeCabinetLatVO.getLatId(), DateUtils.getNowDate(), closeCabinetLatVO.getPersonId(), "关闭柜门操作"));
        return ResultUtils.success("柜格关闭成功");
    }

    @PostMapping("/personRenewal")
    @ApiOperation(value = "个人续借操作")
    public BaseResponse personRenewal(@Valid @RequestBody personRenewalVO personRenewalVO) {
        Date endDate = new Date();
        Borrow borrow = borrowService.getOne(new LambdaQueryWrapper<Borrow>().eq(Borrow::getPersonId, personRenewalVO.getPersonId()).eq(Borrow::getBookId, personRenewalVO.getBookId()));
        if (ObjectUtil.isNull(borrow)) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "未找到对应的借阅信息");
        }
        //判断之前有无续借，没有就直接续借
        if (borrow.getRenewDay() == null && borrow.getRenewTime() == null) {
            borrow.setRenewDay(personRenewalVO.getRenewalDay());
            borrow.setRenewTime(DateUtils.increaseDate(borrow.getStartTime(), personRenewalVO.getRenewalDay()));
            endDate = DateUtils.increaseDate(borrow.getStartTime(), personRenewalVO.getRenewalDay());
        } else {
            Integer day = borrow.getRenewDay() + personRenewalVO.getRenewalDay();
            ConfigType configType = configTypeService.getOne(new LambdaQueryWrapper<ConfigType>().eq(ConfigType::getConfigKey, "renew:book:time"));
            if (day > Integer.valueOf(configType.getConfigValue())) {
                throw new BusinessException(ErrorCode.FORBIDDEN, "续借时间已超过系统最大续借时间限制(" + configType.getConfigValue() + "天)!");
            }
            borrow.setRenewDay(day);
            borrow.setRenewTime(DateUtils.increaseDate(borrow.getRenewTime(), day));
            endDate = DateUtils.increaseDate(borrow.getStartTime(), personRenewalVO.getRenewalDay());
        }
        borrow.setStatus(BorrowStatusEnum.RENEW.getCode());
        borrowService.updateById(borrow);
        deviceLogService.insertDeviceLog(new DeviceLog(null, DateUtils.getNowDate(), personRenewalVO.getPersonId(), "个人续借操作"));
        return ResultUtils.success("续借成功，还书时间截止至:" + endDate);
    }

    @PostMapping("/refreshCabinetLat")
    @ApiOperation("刷新数据")
    public BaseResponse refreshCabinetLat(@Valid @RequestBody List<RefreshBook> refreshBookList) {
        for (RefreshBook refreshBook : refreshBookList) {
            List<Book> updateBooks = new ArrayList<>();
            List<Book> bookByLat = bookService.list(new LambdaQueryWrapper<Book>().eq(Book::getLatId, refreshBook.getLatId()).eq(Book::getIsDeleted, SysConstants.STATE_SYSTEM_ZC));
            if (StringUtils.isEmpty(refreshBook.getRfids())) {
                if (CollectionUtil.isNotEmpty(bookByLat)) {
                    for (Book book : bookByLat) {
                        book.setState(SysConstants.STATE_FILE_QC);
                        book.setUpdateTime(DateUtils.getNowDate());
                    }
                    bookService.updateBatchById(bookByLat);
                }
                continue;
            }
            List<String> rfids = Arrays.asList(refreshBook.getRfids().split(","));
            List<Book> books = bookService.list(new LambdaQueryWrapper<Book>().in(Book::getRfid, rfids));
            //传入rfid，判断是否有借阅，有就删除，然后添加到出库日志
            for (Book book : books) {
                if (!book.getState().equals(SysConstants.STATE_FILE_ZK)) {
                    book.setState(SysConstants.STATE_FILE_ZK);
                    Borrow borrow = borrowService.getOne(new LambdaQueryWrapper<Borrow>().eq(Borrow::getBookId, book.getId()));
                    if (ObjectUtil.isNotNull(borrow)) {
                        borrowService.removeById(borrow.getId());
                    }
                    borrowReturnLogService.insertReturnLog(new ReturnLog(null, book.getId(), SysConstants.INVENT_RETURN_TYPE, DateUtils.getNowDate()));
                }
                if (!book.getLatId().equals(refreshBook.getLatId())) {
                    book.setLatId(refreshBook.getLatId());
                    book.setUpdateTime(DateUtils.getNowDate());
                    updateBooks.add(book);
                }
            }
            //库存书籍盘存，没有传入rfid，直接改出库
            if (CollectionUtil.isNotEmpty(bookByLat)) {
                List<Book> outBooks = bookByLat.stream().filter(book -> !books.stream().anyMatch(b -> b.getRfid().equals(book.getRfid())))
                        .collect(Collectors.toList());
                if (outBooks.size() > 0) {
                    for (Book book : outBooks) {
                        book.setState(SysConstants.STATE_FILE_QC);
                        book.setUpdateTime(DateUtils.getNowDate());
                        updateBooks.add(book);
                    }
                }
            }
            if (CollectionUtil.isNotEmpty(updateBooks)) {
                bookService.updateBatchById(updateBooks);
            }
        }
        deviceLogService.insertDeviceLog(new DeviceLog(null, DateUtils.getNowDate(), null, "设备数据刷新"));
        return ResultUtils.success("刷新成功");
    }
}
